package com.wlit.alarm.utils;

import gnu.io.*;
import io.netty.buffer.ByteBufUtil;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

public class CommPortUtils {

    private static Logger logger = Logger.getLogger(CommPortUtils.class);

    /**
     * 查找端口
     * @param comList
     */
    public static void initComports(List<String> comList){
        Enumeration<CommPortIdentifier> portIdentifiers = CommPortIdentifier.getPortIdentifiers();
        while (portIdentifiers.hasMoreElements()) {
            CommPortIdentifier nextElement = portIdentifiers.nextElement();
            if (nextElement.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                String name = nextElement.getName();
                comList.add(name);
            }
        }
    }

    /**
     * 测试端口的有效性
     * @return
     */
    public static List<String> testCommAvail(){
        List<String> listPortAvail = new ArrayList<>();
        Enumeration<CommPortIdentifier> portIdentifiers = CommPortIdentifier.getPortIdentifiers();
        while (portIdentifiers.hasMoreElements()) {
            CommPortIdentifier nextElement = portIdentifiers.nextElement();
            String name = nextElement.getName();
            CommPort commPort = null;
            try {
                commPort = nextElement.open(name, 3000);
                if (commPort instanceof SerialPort) {
                    SerialPort sp = ((SerialPort) commPort);
                    sp.setSerialPortParams(115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
                    sp.notifyOnDataAvailable(true);
                    sp.notifyOnBreakInterrupt(true);

                    List<byte[]> listDataAvail = new ArrayList<>();
                    sp.addEventListener(new SerialPortEventListener() {
                        @Override
                        public void serialEvent(SerialPortEvent arg0) {
                            if (arg0.getEventType() == SerialPortEvent.DATA_AVAILABLE){
                                byte[] data = CommPortUtils.readFromPort(sp);
                                logger.info("checkCommAvail>>"+ ByteBufUtil.hexDump(data)+">>"+new String(data));
                                if (data!= null && data.length > 0){
                                    listDataAvail.add(data);
                                }
                            }
                        }
                    });
                    //读取信号强度
                    byte[] cmd = SmsUtils.buildRSSI();
                    CommPortUtils.sendToPort(sp, cmd);

                    Thread.sleep(3000);
                    //发送指令能够接收到数据则认为是有效的
                    if (listDataAvail.size() > 0){
                        listPortAvail.add(name);
                    }
                }
                commPort.close();
            }catch (Exception ex){
                ex.printStackTrace();
            }finally {
                if (commPort != null){
                    commPort.close();
                }
            }
        }
        return listPortAvail;
    }

    /**
     * 从端口读数据
     * @param serialPort
     * @return
     */
    public static byte[] readFromPort(SerialPort serialPort) {
        InputStream is = null;
        byte[] bytes = null;
        try {
            is = serialPort.getInputStream();//获得串口的输入流
            int len = is.available();//获得数据长度
            while (len != 0) {
                bytes = new byte[len];//初始化byte数组
                is.read(bytes);
                len = is.available();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                    is = null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return bytes;
    }

    /**
     * 从串口写数据
     * @param serialPort
     * @param order
     */
    public static void sendToPort(SerialPort serialPort, byte[] order) {
        OutputStream out = null;
        try {
            out = serialPort.getOutputStream();
            out.write(order);
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
            //new RuntimeException("信息错误 ： "+ e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                    out = null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


}
